/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * utils.c
 * Copyright (C) chemek anouar 2012 <anouar.chemek@esprit.tn>
 *
 * WiScramb is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WiScramb is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "utils.h"


/**
 * print_mac_header_packet - print the mac header of a sniffed frame
 * @mac_h: Pointer to ieee80211_mac_header struct
 * Returns: void
 */
void print_mac_header_packet ( struct ieee80211_mac_header *mac_h )
{
  //print ieee80211_mac_header
  printf ( "version=%d \n", mac_h->fc.protocol_version );
  printf ( "type=%d \n", mac_h->fc.type );
  printf ( "sub_type=%x \n", mac_h->fc.sub_type );
  printf ( "to_ds=%d \n", mac_h->fc.to_ds );
  printf ( "from_ds=%d \n", mac_h->fc.from_ds );
  printf ( "more_frag=%d \n", mac_h->fc.more_frag );
  printf ( "rety=%d \n", mac_h->fc.rety );
  printf ( "pwr_mgmt=%d \n", mac_h->fc.pwr_mgmt );
  printf ( "more_data=%d \n", mac_h->fc.more_data );
  printf ( "web=%d \n", mac_h->fc.web );
  printf ( "order=%d \n", mac_h->fc.order );
}

/**
 * print_radiotap_header_packet - print the radiotap header of a sniffed frame
 * @plcp_h: Pointer to ieee80211_radiotap_header struct
 * Returns: void
 */
void print_radiotap_header_packet ( struct ieee80211_radiotap_header *plcp_h )
{
  //print ieee80211_plcp_header_packet
  printf ( "header_revesion=%d \n", plcp_h->header_revesion );
  printf ( "header_pad=%d \n", plcp_h->header_pad );
  printf ( "header_lenght=%d \n", plcp_h->header_lenght );
  printf ( "present_flags=%d \n", plcp_h->present_flags );
  printf ( "mac_timestamp=%ld \n", plcp_h->mac_timestamp );
  printf ( "flags=%d \n", plcp_h->flags );
  printf ( "data_rates=%d \n", plcp_h->data_rates );
  printf ( "channel_frequency=%d \n", plcp_h->channel_frequency );
  printf ( "channel_type=%d \n", plcp_h->channel_type );
  printf ( "ssi_signal=%d \n", plcp_h->ssi_signal );
  printf ( "antenna=%d \n", plcp_h->antenna );
  printf ( "rx_flags=%d \n", plcp_h->rx_flags );
}


/**
 * freq_hopper - frequencies hopping every 100 ms 
 * @param: Pointer to wifi interface name argv[1]
 * Returns: NULL on success, EXIT_FAILURE on failure
 */
void * freq_hopper(void *param)
{
	//TODO change this to ioctl calls
  pid_t val;
  char * p=(char *)param;
  int fd; /*file descriptor to the file we will redirect ls's output*/

  if((val =fork()) == -1)
    exit(EXIT_FAILURE);

  if(!val){

      if((fd = open("/dev/null", 0))==-1){ /*open the file */
          perror("open");
      }

      dup2(STDOUT_FILENO,fd); /*copy the file descriptor fd into standard output*/
      dup2(STDERR_FILENO,fd); /* same, for the standard error */
      close(fd); /* close the file descriptor as we don't need it more  */


      execl("../scripts/freq-change.sh","freq-change.sh",p,"&",NULL);
      exit(EXIT_SUCCESS);

  }
  return (NULL);
}



void print_station_adress(u_int8_t *adress)
{
  printf("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X ",adress[0],adress[1],adress[2],adress[3],adress[4],adress[5]);

}

/**
 * ioctl_set_freq - Set frequency/channel, SIOCSIWFREQ
 * @priv: Pointer to private wext data from wpa_driver_wext_init()
 * @freq: Frequency in MHz
 * Returns: 0 on success, -1 on failure
 */
/*
int ioctl_set_freq(int freq)
{


  struct iwreq iwr;
  int ioctl_sock;
  int ret = 0;

  memset(&iwr, 0, sizeof(iwr));
  //strcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
  strncpy (iwr.ifr_ifrn.ifrn_name,iface,sizeof(iwr.ifr_ifrn.ifrn_name));

  iwr.u.freq.m = freq * 100000;
  iwr.u.freq.e = 1;


  if (ioctl(ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
      perror("ioctl[SIOCSIWFREQ]");
      ret = -1;
  }

  return (ret);
}*/

void ieee802_11_parse_elems(u_int8_t *start, size_t len,
                            struct ieee802_11_elems *elems)
{
        size_t left = len;
        u_int8_t *pos = start;

        memset(elems, 0, sizeof(*elems));
        elems->ie_start = start;
        elems->total_len = len;

        while (left >= 2) {
                u_int8_t id, elen;

                id = *pos++;
                elen = *pos++;
                left -= 2;

                if (elen > left)
                        return;

                switch (id) {
                case WLAN_EID_SSID:
                        elems->ssid = pos;
                        elems->ssid_len = elen;
                        break;
                case WLAN_EID_SUPP_RATES:
                        elems->supp_rates = pos;
                        elems->supp_rates_len = elen;
                        break;
                case WLAN_EID_FH_PARAMS:
                        elems->fh_params = pos;
                        elems->fh_params_len = elen;
                        break;
                case WLAN_EID_DS_PARAMS:
                        elems->ds_params = pos;
                        elems->ds_params_len = elen;
                        break;
                case WLAN_EID_CF_PARAMS:
                        elems->cf_params = pos;
                        elems->cf_params_len = elen;
                        break;
                case WLAN_EID_TIM:
                        elems->tim = pos;
                        elems->tim_len = elen;
                        break;
                case WLAN_EID_IBSS_PARAMS:
                        elems->ibss_params = pos;
                        elems->ibss_params_len = elen;
                        break;
                case WLAN_EID_CHALLENGE:
                        elems->challenge = pos;
                        elems->challenge_len = elen;
                        break;
                case WLAN_EID_WPA:
                        if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
                            pos[2] == 0xf2) {
                                /* Microsoft OUI (00:50:F2) */
                                if (pos[3] == 1) {
                                        /* OUI Type 1 - WPA IE */
                                        elems->wpa = pos;
                                        elems->wpa_len = elen;
                                } else if (elen >= 5 && pos[3] == 2) {
                                        if (pos[4] == 0) {
                                                elems->wmm_info = pos;
                                                elems->wmm_info_len = elen;
                                        } else if (pos[4] == 1) {
                                                elems->wmm_param = pos;
                                                elems->wmm_param_len = elen;
                                        }
                                }
                        }
                        break;
                case WLAN_EID_RSN:
                        elems->rsn = pos;
                        elems->rsn_len = elen;
                        break;
                case WLAN_EID_ERP_INFO:
                        elems->erp_info = pos;
                        elems->erp_info_len = elen;
                        break;
                case WLAN_EID_EXT_SUPP_RATES:
                        elems->ext_supp_rates = pos;
                        elems->ext_supp_rates_len = elen;
                        break;
//                case WLAN_EID_HT_CAPABILITY:
//                        if (elen >= sizeof(struct ieee80211_ht_cap))
//                                elems->ht_cap_elem = (void *)pos;
//                        break;
//                case WLAN_EID_HT_INFORMATION:
//                        if (elen >= sizeof(struct ieee80211_ht_info))
//                                elems->ht_info_elem = (void *)pos;
//                        break;
                case WLAN_EID_MESH_ID:
                        elems->mesh_id = pos;
                        elems->mesh_id_len = elen;
                        break;
                case WLAN_EID_MESH_CONFIG:
                        elems->mesh_config = pos;
                        elems->mesh_config_len = elen;
                        break;
                case WLAN_EID_PEER_LINK:
                        elems->peer_link = pos;
                        elems->peer_link_len = elen;
                        break;
                case WLAN_EID_PREQ:
                        elems->preq = pos;
                        elems->preq_len = elen;
                        break;
                case WLAN_EID_PREP:
                        elems->prep = pos;
                        elems->prep_len = elen;
                        break;
                case WLAN_EID_PERR:
                        elems->perr = pos;
                        elems->perr_len = elen;
                        break;
                case WLAN_EID_CHANNEL_SWITCH:
                        elems->ch_switch_elem = pos;
                        elems->ch_switch_elem_len = elen;
                        break;
                case WLAN_EID_QUIET:
                        if (!elems->quiet_elem) {
                                elems->quiet_elem = pos;
                                elems->quiet_elem_len = elen;
                        }
                        elems->num_of_quiet_elem++;
                        break;
                case WLAN_EID_COUNTRY:
                        elems->country_elem = pos;
                        elems->country_elem_len = elen;
                        break;
                case WLAN_EID_PWR_CONSTRAINT:
                        elems->pwr_constr_elem = pos;
                        elems->pwr_constr_elem_len = elen;
                        break;
                case WLAN_EID_TIMEOUT_INTERVAL:
                        elems->timeout_int = pos;
                        elems->timeout_int_len = elen;
                        break;
                default:
                        break;
                }

                left -= elen;
                pos += elen;
        }
}
